package com.millstein.tsinglog.utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

import com.millstein.tsinglog.exception.TsinglogException;
import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.millstein.tsinglog.commons.enums.ResultCode;
import org.springframework.cglib.beans.BeanMap;

public class MyUtils {
	
	private static final Logger LOGGOR = LoggerFactory.getLogger(MyUtils.class);

	/**
	 * 将list转为map，map的键为list元素的id，值为对应list元素
	 * @param list
	 * @param Tclass
	 * @return
	 */
	public static <T> Map<Long, T> transferListToMap(List<T> list, Class<T> Tclass) {
		Map<Long, T> map = new HashMap<Long, T>();
		for(T t : list) {
			Long id;
			try {
				Method getId = Tclass.getDeclaredMethod("getId");
				id = (Long) getId.invoke(t);
			} catch (Exception e) {
				LOGGOR.error("发生异常：{}", e.getMessage(), e);
				throw new TsinglogException(ResultCode.SERVER_OCCURS_ERROR);
			}
			map.put(id, t);
		}
		return map;
	}
	
	/**
	 * 生成uuid
	 * @return
	 */
	public static String genUUID() {
		return UUID.randomUUID().toString().replace("-", "").toUpperCase();
	}

	/**
	 * md5加密算法
	 * @param plainText 未加密的字符串
	 * @return
	 */
	public static String stringToMD5(String plainText) {
		byte[] secretBytes = null;
		try {
			secretBytes = MessageDigest.getInstance("md5").digest(
					plainText.getBytes());
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("没有这个md5算法！");
		}
		String md5code = new BigInteger(1, secretBytes).toString(16);
		for (int i = 0; i < 32 - md5code.length(); i++) {
			md5code = "0" + md5code;
		}
		return md5code;
	}
	
	/**
	 * 将对象属性转化为map结合
	 */
	public static <T> Map<String, Object> beanToMap(T bean) {
		Map<String, Object> map = new HashMap<>();
		if (bean != null) {
			BeanMap beanMap = BeanMap.create(bean);
			for (Object key : beanMap.keySet()) {
				map.put(key + "", beanMap.get(key));
			}
		}
		return map;
	}

	/**
	 * 将map集合中的数据转化为指定对象的同名属性中
	 */
	public static <T> T mapToBean(Map<String, Object> map, Class<T> clazz) throws Exception {
		T bean = clazz.newInstance();
		BeanMap beanMap = BeanMap.create(bean);
		beanMap.putAll(map);
		return bean;
	}


	/**
	 * 将数据库表的字段名称转为实体类的属性名称，如：
	 * 		is_released -> isReleased
	 * @param field 字段名称
	 * @return
	 */
	public static String fieldToProperty(String field) {
		if (null == field) {
			return "";
		}
		char[] chars = field.toCharArray();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < chars.length; i++) {
			char c = chars[i];
			if (c == '_') {
				int j = i + 1;
				if (j < chars.length) {
					sb.append(StringUtils.upperCase(CharUtils.toString(chars[j])));
					i++;
				}
			} else {
				sb.append(c);
			}
		}
		return sb.toString();
	}

	/**
	 * 将数据库表的查询结果map转为实体类属性的map，如
	 * 		{"id": 5, "category_id": 1, "is_released": 1} -> {"id": 5, "categoryId": 1, "isReleased": 1}
	 * @param ColumnMap 数据库表的查询结果
	 * @return
	 */
	public static Map<String, Object> transColumnMapToFieldMap(Map<String, Object> ColumnMap) {
		Map<String, Object> map = new HashMap<>();

		for (Map.Entry<String, Object> entry : ColumnMap.entrySet()) {
			map.put(fieldToProperty(entry.getKey()), entry.getValue());
		}
		return map;
	}



	/**
	 * 将map集合中的数据转化为指定对象的同名属性中，并且根据需要的类型对值进行相应的转换
	 */
	public static <T> T refelctBean(Map map , Class<T> clazz) throws Exception {
		T bean = null;
		try {
			bean = clazz.newInstance();
			Method[] methods = clazz.getDeclaredMethods();
			for (Method method : methods) {
				if(method.getName().startsWith("set")){
					String key = method.getName().replace("set", "");
					key = key.substring(0, 1).toLowerCase().concat(key.substring(1));
					Object value = map.get(key);
					if(value==null || value.equals("N/A")) continue;
					Class<?>[]  paramType = method.getParameterTypes();
					//根据参数类型执行对应的set方法给vo赋值
					if (paramType[0] == String.class) {
						method.invoke(bean, String.valueOf(value));
						continue;
					} else if(paramType[0] == BigDecimal.class) {
						method.invoke(bean, new BigDecimal(value.toString()));
						continue;
					} else if (paramType[0] == Double.class) {
						method.invoke(bean, Double.parseDouble(value.toString()));
						continue;
					} else if (paramType[0] == int.class || paramType[0] == Integer.class) {
						method.invoke(bean, Integer.valueOf(value.toString()));
						continue;
					} else if (paramType[0] == Boolean.class){
						method.invoke(bean, Boolean.parseBoolean(value.toString()));
						continue;
					} else if (paramType[0] == char.class || paramType[0] == Character.class) {
						method.invoke(bean, value.toString().charAt(0));
						continue;
					} else if (paramType[0] == long.class || paramType[0] == Long.class) {
						method.invoke(bean, Long.valueOf(value.toString()));
						continue;
					} else if (paramType[0] == short.class || paramType[0] == Short.class) {
						method.invoke(bean, Short.valueOf(value.toString()));
						continue;
					}
				}
			}
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return bean;
	}


	/**
	 * 生成指定范围的随机数
	 * @param min
	 * @param max
	 */
	public static int getRandomNum(int min, int max) {
		Random random = new  Random();

		int result = random.nextInt(max) % (max - min + 1) + min;
		return result;
	}

}
